package org.darkforest.common.services.impl;

import org.apache.commons.collections.CollectionUtils;
import org.darkforest.common.services.BusinessPropertiesService;
import org.darkforest.common.services.EmployeeAssignmentService;
import org.darkforest.enums.EmployeeLevel;
import org.darkforest.model.Member;
import org.darkforest.ucenter.service.MemberLevelService;
import org.darkforest.ucenter.service.MemberPathService;
import org.darkforest.ucenter.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * EmployeeAssignmentServiceImpl
 * Created by Justin on 15/5/27.
 */

@Transactional(propagation = Propagation.REQUIRED)
@Service
public class EmployeeAssignmentServiceImpl implements EmployeeAssignmentService {

    @Autowired
    private MemberPathService memberPathService;

    @Autowired
    private MemberLevelService memberLevelService;

    @Autowired
    @Qualifier("memberServiceImpl")
    private MemberService memberService;

    @Autowired
    private BusinessPropertiesService propertiesService;


    @Override
    public void assign(Integer memberId, Integer assignTo) {
        if (memberId == null || assignTo == null) {
            throw new IllegalArgumentException("both member id cannot be null");
        }
        Member assignToMember = memberService.findMemberById(assignTo);
        if (assignToMember == null) {
            throw new IllegalArgumentException("assign to member is not exist");
        }
        memberPathService.appendTo(memberId, assignTo);
    }

    @Override
    public void assignToLevel(Integer memberId, EmployeeLevel employeeLevel) {
        if (employeeLevel == null || memberId == null) {
            throw new IllegalArgumentException("member id and level cannot be null");
        }
        int level = employeeLevel.ordinal();

        if (level == 0) {
            memberLevelService.setEmployeeLevel(memberId, level);
            memberPathService.setToRoot(memberId);
        } else {
            String indexKey = propertiesService.getProperty(LevelIndexKey.getKey(level));
            memberLevelService.setEmployeeLevel(memberId, level + 1);
            Integer parent = findRandomParentNode(indexKey, level);
            memberPathService.appendTo(memberId, parent);
            propertiesService.setProperty(indexKey, parent.toString());
        }
    }

    private Integer findRandomParentNode(String indexKey, Integer parentLevel) {
        List<Member> parents = memberLevelService.getEmployeesByLevel(EmployeeLevel.values()[parentLevel]);
        if (CollectionUtils.isEmpty(parents)) {
            throw new IllegalArgumentException("Level " + parentLevel + " doesn't has any member. Assign failed");
        }
        return LevelIndexKey.getNext(parents, indexKey);
    }

    @Override
    public void assign(Integer memberId) {
        assignToLevel(memberId, EmployeeLevel.LEVEL_2);
    }
}
